package com.ccom.core.common.aspect;

import com.ccom.core.common.annotation.Batch;
import com.ccom.core.common.enums.BatchType;
import com.ccom.core.common.util.CollectionUtils;
import com.ccom.core.common.util.EmptyUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 增删改查批量处理aop
 * @Author: zjj
 * @Date: 2021年12月13日
 */
@Aspect
public class BatchAop {
    private static final Logger logger = LoggerFactory.getLogger(BatchAop.class);

    @SuppressWarnings("unchecked")
    public Object batch(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) thisJoinPoint.getSignature();

        //实际调用的方法
        Method method = signature.getMethod();
        Batch annotation = method.getAnnotation(Batch.class);
        if (null == annotation) {
            return thisJoinPoint.proceed();
        }

        Object[] args = thisJoinPoint.getArgs();
        if (EmptyUtils.isIllegalArray(args)) {
            return thisJoinPoint.proceed();
        }

        Object arg = args[0];
        if (arg instanceof List) {
            if (EmptyUtils.isEmpty((List<?>) arg)) {
                return thisJoinPoint.proceed();
            }
            List list = (List) arg;
            int size = annotation.size();
            if (list.size() < size) {
                return thisJoinPoint.proceed();
            }
            //把list处理成多个list,分批执行
            List<? extends List<?>> split = CollectionUtils.split(list, size);
            Object target = thisJoinPoint.getTarget();
            BatchType type = annotation.type();
            if (type == BatchType.QUERY) {
                return query(split, method, target, args);
            }
            return common(split, method, target, args);
        } else {
            return thisJoinPoint.proceed();
        }
    }

    /**
     * @param split   分割后的数据
     * @param method  拦截的方法
     * @param target  调用的对象
     * @param objects 调用的参数
     * @Description: 将查询条件的List拆分多次，然后查询并返回
     */
    @SuppressWarnings("unchecked")
    private Object query(List<? extends List<?>> split, Method method, Object target, Object[] objects) throws Exception {
        List list = new ArrayList();
        for (List<?> l : split) {
            objects[0] = l;
            List invoke = (List) method.invoke(target, objects);
            list.addAll(invoke);
        }
        return list;
    }

    /**
     * @param split   分割后的数据
     * @param method  拦截的方法
     * @param target  调用的对象
     * @param objects 调用的参数
     * @Description: 数据删除、修改、更新 暂时不返回更新数量
     */
    @SuppressWarnings("unchecked")
    private Object common(List<? extends List<?>> split, Method method, Object target, Object[] objects) throws Exception {
        for (List<?> l : split) {
            objects[0] = l;
            method.invoke(target, objects);
        }
        return null;
    }
}
